package com.sinosoft.comm.controller;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;

import com.sinosoft.comm.condition.BaseCondition;
import com.sinosoft.comm.entity.BaseEntity;
import com.sinosoft.comm.service.BaseService;
import com.sinosoft.comm.util.PageUtil;
import com.sinosoft.comm.util.SpringContext;
import com.sinosoft.enums.YesOrNoEnum;
import com.sinosoft.enums.http.StatusCode;
import com.sinosoft.utils.RedisKeyConf;
import com.sinosoft.utils.RedisUtil;
import com.sinosoft.utils.classzz.ClassUtil;
import com.sinosoft.vo.http.Result;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import java.util.Iterator;
import java.util.List;

@Scope("prototype")
public class CommonController<T extends BaseEntity, S extends BaseService<T, F>, F extends BaseCondition> {

    private T entity;
    protected S service;

    @Autowired
    RedisUtil redisUtil;

    @RequestMapping(value = "/add", method = {RequestMethod.POST, RequestMethod.GET})
    public String add(ModelMap modelMap, F condition) {
        modelMap.addAttribute("condition", condition);
        return ClassUtil.camelToUnderline(this.getEntity().getClass().getSimpleName()) + "/add";
    }

    @RequestMapping(value = "/edit", method = {RequestMethod.POST, RequestMethod.GET})
    public String edit(ModelMap modelMap, String id) {
        System.out.println("id:" + id);
        modelMap.addAttribute("entity", this.getService().getById(id));
        return ClassUtil.camelToUnderline(this.getEntity().getClass().getSimpleName()) + "/edit";
    }

    @RequestMapping(value = "/list", method = {RequestMethod.POST, RequestMethod.GET})
    public String list(ModelMap modelMap, F condition) {
        PageInfo<T> pageInfo = this.getService().getPageList(condition);
        modelMap.addAttribute("pageList", pageInfo.getList());
        modelMap.addAttribute("pageStr", PageUtil.createPageStr(condition, pageInfo.getPageNum(), pageInfo.getPages(), pageInfo.getTotal()));
        modelMap.addAttribute("condition", condition);
        return ClassUtil.camelToUnderline(this.getEntity().getClass().getSimpleName()) + "/list";
    }

    /**
     * @param @param  entity
     * @param @return 参数
     * @return ResultEntity<T>    返回类型
     * @throws
     * @Title: getById
     * @Description: TODO(根据ID查找)
     * @author cj
     * @date 2019年2月25日 下午5:54:33
     */

    @ApiOperation(value = "通用根据ID取得对象", notes = "通用根据ID取得对象")
    @PostMapping(value = "/getById")
    public Result<T> getById(HttpServletRequest request, @RequestParam @ApiParam(value = "通用根据ID取得对象", required = true) String id) {
        return Result.ok().setData(this.getService().getById(id));
    }

    /**
     * @param @param  filter
     * @param @return 参数
     * @return ResultEntity<PageInfo       <       T>>    返回类型
     * @throws
     * @Title: list
     * @Description: TODO(统一列表)
     * @author cj
     * @date 2019年2月25日 下午5:58:13
     */
    @ApiOperation(value = "通用列表接口", notes = "通用列表接口")
    @PostMapping(value = "/listapi")
    public Result<PageInfo<T>> listapi(HttpServletRequest request, @RequestBody F condition) {
        //System.out.println("filter:"+filter);
        //System.out.println("service:"+this.getService());
        return Result.ok().setData(this.getService().getPageList(condition));
    }

    /**
     * @param @param  ids
     * @param @return 参数
     * @return ResultEntity<Object>    返回类型
     * @throws
     * @Title: delAll
     * @Description: TODO(统一删除)
     * @author cj
     * @date 2019年2月25日 下午6:04:52
     */
    @ApiOperation(value = "通用删除接口", notes = "通用删除接口")
    @RequestMapping(value = "/delAll", produces = "application/json; charset=utf-8", method = {RequestMethod.POST})
    @ResponseBody
    public Result<Object> delAll(HttpServletRequest request, @RequestBody List<String> ids) {
        try {
            int flag = this.getService().delAll(ids);
            if (flag == -1) {
                return Result.failure(StatusCode.SERVER_ERROR);
            } else {
                return Result.ok().setData(YesOrNoEnum.YES.getCode());
            }
        } catch (Exception e) {
            return Result.failure(StatusCode.SERVER_ERROR).setData(e.getMessage());
        }
    }

    @ApiOperation(value = "通用添加接口", notes = "通用添加接口")
    @RequestMapping(value = "/saveAdd", method = {RequestMethod.POST})
    @ResponseBody
    public Result<Object> saveAdd(HttpServletRequest request, @ApiParam @Validated T entity, BindingResult result) {
        return save(request, entity, result);
    }

    @ApiOperation(value = "通用编辑接口", notes = "通用编辑接口")
    @RequestMapping(value = "/saveEdit", method = {RequestMethod.POST})
    @ResponseBody
    public Result<Object> saveEdit(HttpServletRequest request, @ApiParam @Validated T entity, BindingResult result) {
        if (StringUtils.isEmpty(entity.getId())) {
            return Result.failure(StatusCode.FAILURE);
        }
        return save(request, entity, result);
    }

    @ApiIgnore//使用该注解忽略这个API
    protected Result save(HttpServletRequest request, T entity, BindingResult result) {
        // 现在表示执行的验证出现错误
        try {
            if (result.hasErrors()) {
                return Result.failure(StatusCode.FAILURE).setDescription(validateErro(result));
            } else {
                entity = initUser(request, entity);
                entity = this.getService().save(entity);
                if (entity != null) {
                    return Result.ok().setData(entity);
                } else {
                    return Result.failure(StatusCode.FAILURE);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Result.failure(StatusCode.SERVER_ERROR).setDescription(e.getMessage());

        }
    }

    public T initUser(HttpServletRequest request, T entity) {
        JSONObject sysUser = getSysUser(request);
        if (sysUser != null) {
            if (StringUtils.isEmpty(entity.getId())) {
                entity.setCreateUser(sysUser.getString("code"));
            } else {
                entity.setUpdateUser(sysUser.getString("code"));
            }
        }
        return entity;
    }

    public JSONObject getSysUser(HttpServletRequest request) {
        String accessToken = request.getHeader("Authorization");
        if (accessToken != null && redisUtil.exists(RedisKeyConf.API_USERKEY + accessToken)) {
            return (JSONObject) redisUtil.get(RedisKeyConf.API_USERKEY + accessToken);
        }
        return null;
    }


    public S getService() {
        //System.out.println("----------------------------------:service:"+service);
        if (service == null) {
            Class<?> c = ClassUtil.getSuperClassGenricType(getClass(), 1);
            //System.out.println("===:"+ClassUtil.getSuperClassGenricType(getClass(), 1).getSimpleName());
            //System.out.println("springContext:"+springContext);
            this.setService((S) SpringContext.getServiceBeansByClass(c));
            //System.out.println("service:"+service);
        }
        return service;
    }

    public T getEntity() {
        //System.out.println("----------------------------------:service:"+service);
        if (entity == null) {
            try {
                entity = (T) ClassUtil.getSuperClassGenricType(getClass(), 0).newInstance();
            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return entity;
    }

    public void setService(S service) {
        this.service = service;
    }

    protected String validateErro(BindingResult result) {
        StringBuffer msg = new StringBuffer();
        Iterator<ObjectError> iterator = result.getAllErrors().iterator(); // 获取全部错误信息
        while (iterator.hasNext()) {
            ObjectError error = iterator.next();    // 取出每一个错误
            msg.append(error.getDefaultMessage()).append(",");
            System.out.println("【错误信息】code = " + error.getCode() + "，message = " + error.getDefaultMessage());
        }
        return msg.toString();
    }
}
